﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Web;
using Framework.Mvc.Attributes;

namespace OnlineMealOrdering.Extends.MvcPager
{

    public class DataColumn
    {
        public string Name { get; set; }
        public string DisplayName { get; set; }
        public bool Visible { get; set; }
        public Type Type { get; set; }
        public int Index { get; set; }

        public static DataColumn Create(string name, string p1, Type propertyType, bool visible = true, bool sortable = true)
        {
            return new DataColumn() { Name = name, DisplayName = p1, Type = propertyType, Visible = visible };
        }
    }

    public static class MvcPagerViewHelp
    {
        public static string GetPropertyName<TModel>(Expression<Func<TModel, object>> expr)
        {
            var name = "";
            if (expr.Body is UnaryExpression)
            {
                name = ((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.Name;
            }
            else if (expr.Body is MemberExpression)
            {
                name = ((MemberExpression)expr.Body).Member.Name;
            }
            else if (expr.Body is ParameterExpression)
            {
                name = ((ParameterExpression)expr.Body).Type.Name;
            }
            return name;
        }

        private static Dictionary<string, IEnumerable<DataColumn>> Cache = new Dictionary<string, IEnumerable<DataColumn>>();

        public static IEnumerable<DataColumn> GetModelColumns<TResult>()
        {
            var typeName = typeof(TResult).FullName;
            if (Cache.ContainsKey(typeName))
            {
                return Cache[typeName];
            }

            IEnumerable<DataColumn> columns = null;
            if (columns == null || !columns.Any())
            {
                var propInfos = GetSortedProperties<TResult>();
                var columnList = new List<DataColumn>();
                foreach (var propertyInfo in propInfos)
                {
                    var displayNameAttribute = (DisplayNameAttribute)propertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false).FirstOrDefault();
                    var displayName = displayNameAttribute == null ? propertyInfo.Name : displayNameAttribute.DisplayName;

                    var visibleAttribute = (DataTablesVisibleAttribute)propertyInfo.GetCustomAttributes(typeof(DataTablesVisibleAttribute), false).FirstOrDefault();
                    var visible = visibleAttribute == null ? true : visibleAttribute.Visible;

                    var orderByOrderIndexAttribute = (DataTableOrderByIndexAttribute)propertyInfo.GetCustomAttributes(typeof(DataTableOrderByIndexAttribute), false).FirstOrDefault();
                    var orderByOrderIndex = orderByOrderIndexAttribute == null ? 0 : orderByOrderIndexAttribute.Index;

                    columnList.Add(new DataColumn()
                    {
                        Name = propertyInfo.Name,
                        DisplayName = displayName,
                        Visible = visible,
                        Type = propertyInfo.PropertyType,
                        Index = orderByOrderIndex
                    });
                }
                columns = columnList.OrderBy(a => a.Index).ToArray();
                Cache.Add(typeName, columns);
            }
            return columns;
        }

        public static IEnumerable<PropertyInfo> GetSortedProperties(this Type t)
        {
            return from pi in t.GetProperties()
                   let da = (DisplayAttribute)pi.GetCustomAttributes(typeof(DisplayAttribute), false).SingleOrDefault()
                   let order = ((da != null && da.GetOrder() != null && da.GetOrder() >= 0) ? da.Order : int.MaxValue)
                   orderby order
                   select pi;
        }

        public static IEnumerable<PropertyInfo> GetSortedProperties<T>()
        {
            return typeof(T).GetSortedProperties();
        }
    }



}